home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / START HERE - Box / Box3DSupport.c < prev    next >
Encoding:
Text File  |  1997-08-14  |  10.8 KB  |  409 lines  |  [TEXT/CWIE]

  1. // My3dSupport.c - QuickDraw 3d routines
  2. //
  3. // This file contains utility routines for QuickDraw 3d sample code.
  4. // This is a simple QuickDraw 3d application to draw a cube in the center 
  5. // of the main application window.  The routines in here handle setting up
  6. // the main display group, the view, the Macintosh 3D draw context, and the
  7. // camera and lighting. 
  8. //
  9. // This code is the basis of the introductory article in  d e v e l o p  issue 22
  10. //
  11. // Nick Thompson - January 6th 1995
  12. // 
  13. // ©1994-95 Apple computer Inc., All Rights Reserved
  14. //
  15.  
  16. #include <QuickDraw.h>
  17. #include <QDOffScreen.h>
  18.  
  19.  
  20. #include "Box3DSupport.h"
  21.  
  22.  
  23. #include "QD3DDrawContext.h"
  24. #include "QD3DRenderer.h"
  25. #include "QD3DShader.h"
  26. #include "QD3DCamera.h"
  27. #include "QD3DLight.h"
  28. #include "QD3DGeometry.h"
  29. #include "QD3DGroup.h"
  30. #include "QD3DMath.h"
  31. #include "QD3DSet.h"
  32. #include "QD3DTransform.h"
  33. #include "QD3DAcceleration.h"
  34.  
  35. static     TQ3Point3D    documentGroupCenter;
  36. static    float        documentGroupScale;
  37.  
  38.  
  39. TQ3ViewObject MyNewView(WindowPtr theWindow)
  40. {
  41.     TQ3Status                myStatus;
  42.     TQ3ViewObject            myView;
  43.     TQ3DrawContextObject        myDrawContext;
  44.     TQ3RendererObject        myRenderer;
  45.     TQ3CameraObject            myCamera;
  46.     TQ3GroupObject            myLights;
  47.     
  48.     myView = Q3View_New();
  49.     
  50.     //    Create and set draw context.
  51.     if ((myDrawContext = MyNewDrawContext(theWindow)) == nil )
  52.         goto bail;
  53.         
  54.     if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
  55.         goto bail;
  56.  
  57.     Q3Object_Dispose( myDrawContext ) ;
  58.     
  59.     //    Create and set renderer.
  60.     
  61.     
  62.     
  63.     // this would use the wireframe renderer
  64. #if 0
  65.  
  66.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  67.     if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  68.         goto bail;
  69.     }
  70.     
  71. #else
  72.  
  73.     // this would use the interactive software renderer
  74.  
  75.     if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) {
  76.         if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  77.             goto bail;
  78.         }
  79.         // these two lines set us up to use the best possible renderer,
  80.         // including  hardware if it is installed.
  81.         Q3InteractiveRenderer_SetDoubleBufferBypass (myRenderer, kQ3True);                        
  82.         Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0);
  83.         
  84.         /*
  85.          * the line below would force the use of the software rasterizer 
  86.          *
  87.          * Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_Apple, kQAEngine_AppleSW);
  88.          *
  89.          */
  90.  
  91.     }
  92.     else {
  93.         goto bail;
  94.     }
  95. #endif
  96.  
  97.     Q3Object_Dispose( myRenderer ) ;
  98.     
  99.     //    Create and set camera.
  100.     if ( (myCamera = MyNewCamera(theWindow)) == nil )
  101.         goto bail;
  102.         
  103.     if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
  104.         goto bail;
  105.  
  106.     Q3Object_Dispose( myCamera ) ;
  107.     
  108.     //    Create and set lights.
  109.     if ((myLights = MyNewLights()) == nil )
  110.         goto bail;
  111.         
  112.     if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
  113.         goto bail;
  114.         
  115.     Q3Object_Dispose(myLights);
  116.  
  117.     //    Done!!!
  118.     return ( myView );
  119.     
  120. bail:
  121.     //    If any of the above failed, then don't return a view.
  122.     return ( nil );
  123. }
  124.  
  125. //----------------------------------------------------------------------------------
  126.  
  127. TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow)
  128. {
  129.     TQ3DrawContextData        myDrawContextData;
  130.     TQ3MacDrawContextData    myMacDrawContextData;
  131.     TQ3ColorARGB            ClearColor;
  132.     TQ3DrawContextObject    myDrawContext ;
  133.     
  134.     //    Set the background color.
  135.     ClearColor.a = 1.0;
  136.     ClearColor.r = 1.0;
  137.     ClearColor.g = 1.0;
  138.     ClearColor.b = 1.0;
  139.     
  140.     //    Fill in draw context data.
  141.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  142.     myDrawContextData.clearImageColor = ClearColor;
  143.     myDrawContextData.paneState = kQ3False;
  144.     myDrawContextData.maskState = kQ3False;
  145.     myDrawContextData.doubleBufferState = kQ3True;
  146.  
  147.     myMacDrawContextData.drawContextData = myDrawContextData;
  148.     
  149.     myMacDrawContextData.window = (CGrafPtr) theWindow;        // this is the window associated with the view
  150.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  151.     myMacDrawContextData.viewPort = nil;
  152.     myMacDrawContextData.grafPort = nil;
  153.     
  154.     //    Create draw context and return it, if it’s nil the caller must handle
  155.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  156.  
  157.     return myDrawContext ;
  158. }
  159.  
  160. //----------------------------------------------------------------------------------
  161.  
  162. TQ3CameraObject MyNewCamera(WindowPtr theWindow)
  163. {
  164.     TQ3ViewAngleAspectCameraData    perspectiveData;
  165.     TQ3CameraObject                camera;
  166.     
  167.     TQ3Point3D                     from     = { 0.0, 0.0, 7.0 };
  168.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  169.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  170.  
  171.     float                         fieldOfView = 1.0;
  172.     float                         hither         = 1.0;
  173.     float                         yon         = 1000;
  174.     
  175.     TQ3Status                    returnVal = kQ3Failure ;
  176.  
  177.  
  178.     perspectiveData.cameraData.placement.cameraLocation     = from;
  179.     perspectiveData.cameraData.placement.pointOfInterest     = to;
  180.     perspectiveData.cameraData.placement.upVector             = up;
  181.  
  182.     perspectiveData.cameraData.range.hither    = hither;
  183.     perspectiveData.cameraData.range.yon     = yon;
  184.  
  185.     perspectiveData.cameraData.viewPort.origin.x = -1.0;
  186.     perspectiveData.cameraData.viewPort.origin.y = 1.0;
  187.     perspectiveData.cameraData.viewPort.width = 2.0;
  188.     perspectiveData.cameraData.viewPort.height = 2.0;
  189.     
  190.     perspectiveData.fov                = fieldOfView;
  191.     perspectiveData.aspectRatioXToY    =
  192.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  193.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  194.         
  195.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  196.  
  197.     return camera ;
  198. }
  199.  
  200.  
  201. //----------------------------------------------------------------------------------
  202.  
  203. TQ3GroupObject MyNewLights()
  204. {
  205.     TQ3GroupPosition        myGroupPosition;
  206.     TQ3GroupObject            myLightList;
  207.     TQ3LightData            myLightData;
  208.     TQ3PointLightData        myPointLightData;
  209.     TQ3DirectionalLightData    myDirectionalLightData;
  210.     TQ3LightObject            myAmbientLight, myPointLight, myFillLight;
  211.     TQ3Point3D                pointLocation = { -10.0, 0.0, 10.0 };
  212.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  213.     TQ3ColorRGB                WhiteLight = { 1.0, 1.0, 1.0 };
  214.     
  215.     //    Set up light data for ambient light.  This light data will be used for point and fill
  216.     //    light also.
  217.  
  218.     myLightData.isOn = kQ3True;
  219.     myLightData.color = WhiteLight;
  220.     
  221.     //    Create ambient light.
  222.     myLightData.brightness = .2;
  223.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  224.     if ( myAmbientLight == nil )
  225.         goto bail;
  226.     
  227.     //    Create point light.
  228.     myLightData.brightness = 1.0;
  229.     myPointLightData.lightData = myLightData;
  230.     myPointLightData.castsShadows = kQ3False;
  231.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  232.     myPointLightData.location = pointLocation;
  233.     myPointLight = Q3PointLight_New(&myPointLightData);
  234.     if ( myPointLight == nil )
  235.         goto bail;
  236.  
  237.     //    Create fill light.
  238.     myLightData.brightness = .2;
  239.     myDirectionalLightData.lightData = myLightData;
  240.     myDirectionalLightData.castsShadows = kQ3False;
  241.     myDirectionalLightData.direction = fillDirection;
  242.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  243.     if ( myFillLight == nil )
  244.         goto bail;
  245.  
  246.     //    Create light group and add each of the lights into the group.
  247.     myLightList = Q3LightGroup_New();
  248.     if ( myLightList == nil )
  249.         goto bail;
  250.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  251.     if ( myGroupPosition == 0 )
  252.         goto bail;
  253.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  254.     if ( myGroupPosition == 0 )
  255.         goto bail;
  256.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  257.     if ( myGroupPosition == 0 )
  258.         goto bail;
  259.  
  260.     Q3Object_Dispose( myAmbientLight ) ;
  261.     Q3Object_Dispose( myPointLight ) ;
  262.     Q3Object_Dispose( myFillLight ) ;
  263.  
  264.     //    Done!
  265.     return ( myLightList );
  266.     
  267. bail:
  268.     //    If any of the above failed, then return nothing!
  269.     return ( nil );
  270. }
  271.  
  272.  
  273.  
  274.  
  275. static void MyColorBoxFaces( TQ3BoxData *myBoxData )
  276. {
  277.     TQ3ColorRGB                faceColor ;
  278.     short                     face ;
  279.     
  280.     // sanity check - you need to have set up 
  281.     // the face attribute set for the box data 
  282.     // before calling this.
  283.     
  284.     if( myBoxData->faceAttributeSet == NULL )
  285.         return ;
  286.         
  287.     // make each face of a box a different color
  288.     
  289.     for( face = 0; face < 6; face++) {
  290.         
  291.         myBoxData->faceAttributeSet[face] = Q3AttributeSet_New();
  292.         switch( face ) {
  293.             case 0:
  294.                 faceColor.r = 1.0;
  295.                 faceColor.g = 0.0;
  296.                 faceColor.b = 0.0;
  297.                 break;
  298.             
  299.             case 1:
  300.                 faceColor.r = 0.0;
  301.                 faceColor.g = 1.0;
  302.                 faceColor.b = 0.0;
  303.                 break;
  304.             
  305.             case 2:
  306.                 faceColor.r = 0.0;
  307.                 faceColor.g = 0.0;
  308.                 faceColor.b = 1.0;
  309.                 break;
  310.             
  311.             case 3:
  312.                 faceColor.r = 1.0;
  313.                 faceColor.g = 1.0;
  314.                 faceColor.b = 0.0;
  315.                 break;
  316.             
  317.             case 4:
  318.                 faceColor.r = 1.0;
  319.                 faceColor.g = 0.0;
  320.                 faceColor.b = 1.0;
  321.                 break;
  322.             
  323.             case 5:
  324.                 faceColor.r = 0.0;
  325.                 faceColor.g = 1.0;
  326.                 faceColor.b = 1.0;
  327.                 break;
  328.         }
  329.         Q3AttributeSet_Add(myBoxData->faceAttributeSet[face], kQ3AttributeTypeDiffuseColor, &faceColor);
  330.     }
  331. }
  332.  
  333. static TQ3GroupPosition MyAddTransformedObjectToGroup( TQ3GroupObject theGroup, TQ3Object theObject, TQ3Vector3D *translation )
  334. {
  335.     TQ3TransformObject    transform;
  336.  
  337.     transform = Q3TranslateTransform_New(translation);
  338.     Q3Group_AddObject(theGroup, transform);    
  339.     Q3Object_Dispose(transform);
  340.     return Q3Group_AddObject(theGroup, theObject);    
  341. }
  342.  
  343.  
  344. TQ3GroupObject MyNewModel()
  345. {
  346.     TQ3GroupObject            myGroup = NULL;
  347.     TQ3GeometryObject        myBox;
  348.     TQ3BoxData                myBoxData;
  349.     TQ3ShaderObject            myIlluminationShader ;
  350.     TQ3Vector3D                translation;
  351.     
  352.     TQ3SetObject                faces[6] ;
  353.     short                    face ;
  354.             
  355.     // Create a group for the complete model.
  356.     // do not use Q3OrderedDisplayGroup_New since in this
  357.     // type of group all of the translations are applied before
  358.     // the objects in the group are drawn, in this instance we 
  359.     // dont want this.
  360.     if ((myGroup = Q3DisplayGroup_New()) != NULL ) {
  361.             
  362.         // Define a shading type for the group
  363.         // and add the shader to the group
  364.         myIlluminationShader = Q3PhongIllumination_New();
  365.         Q3Group_AddObject(myGroup, myIlluminationShader);
  366.  
  367.         // set up the colored faces for the box data
  368.         myBoxData.faceAttributeSet = faces;
  369.         myBoxData.boxAttributeSet = nil;
  370.         MyColorBoxFaces( &myBoxData ) ;
  371.         
  372.         // create the box itself
  373.         Q3Point3D_Set(&myBoxData.origin, 0, 0, 0);
  374.         Q3Vector3D_Set(&myBoxData.orientation, 0, 1, 0);
  375.         Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 1);    
  376.         Q3Vector3D_Set(&myBoxData.minorAxis, 1, 0, 0);    
  377.         myBox = Q3Box_New(&myBoxData);
  378.         
  379.         // put four copies of the box into the group, each one with its own translation
  380.         translation.x = 0;translation.y = 0;translation.z = 0;
  381.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  382.         
  383.         translation.x = 2;translation.y = 0;translation.z = 0;
  384.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  385.         
  386.         translation.x = 0;translation.y = 0;translation.z = -2;
  387.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  388.         
  389.         translation.x = -2;translation.y = 0;translation.z = 0;
  390.         MyAddTransformedObjectToGroup( myGroup, myBox, &translation ) ;
  391.     }
  392.     
  393.     // dispose of the objects we created here
  394.     if( myIlluminationShader ) 
  395.         Q3Object_Dispose(myIlluminationShader);    
  396.             
  397.     for( face = 0; face < 6; face++) {
  398.         if( myBoxData.faceAttributeSet[face] != NULL )
  399.             Q3Object_Dispose(myBoxData.faceAttributeSet[face]);
  400.     }
  401.     
  402.     if( myBox ) 
  403.         Q3Object_Dispose( myBox );
  404.     
  405.     //    Done!
  406.     return ( myGroup );
  407. }
  408.  
  409.